import axios from 'axios'
import store from '@/store'
import { setToken, getToken } from '@/utils/auth'
import { filterData } from '@/utils/filter'
import router from '@/router'
import { Message } from 'element-ui'

// 是否正在刷新的标记
let isRefreshing = false

// 重试队列，每一项将是一个待执行的函数形式
let requests = []

const reload = async () => {
  await store.dispatch('user/resetToken')
  const fullPath = router.currentRoute.fullPath
  router.replace({ path: '/login', query: { redirect: fullPath } })
}

// create an axios instance
const service = axios.create({
  baseURL: process.env.VUE_APP_BASE_URL,
  // withCredentials: true,
  timeout: 5000
})

// 刷新token的请求实例
const refresh = axios.create({
  baseURL: process.env.VUE_APP_BASE_URL,
  method: 'post',
  timeout: 5000
})

const refreshAxios = function () {
  return refresh({
    url: '/u/api/v2/auth/refresh_token'
  })
}

// 普通请求的响应拦截器
service.interceptors.request.use(
  config => {
    const token = getToken('token')
    if (token) {
      config.headers.token = token
    }
    config.data = filterData(config.data)
    config.params = filterData(config.params)
    return config
  },
  error => {
    return Promise.reject(error)
  }
)

// 刷新token请求的请求拦截器
refresh.interceptors.request.use(
  config => {
    const refreshToken = getToken('refreshToken')
    if (refreshToken) {
      config.headers.refresh_token = refreshToken
    }
    return config
  },
  err => {
    return Promise.reject(err)
  }
)

// 普通请求的响应拦截器
service.interceptors.response.use(
  response => {
    const { data } = response
    const { code, msg } = data
    const config = response.config
    if (code !== 200) {
      if (code === 1005 || code === 1007) {
        if (!isRefreshing) {
          isRefreshing = true
          return refreshAxios()
            .then(res => {
              isRefreshing = false
              const { token, refreshToken } = res.data
              setToken('token', token)
              setToken('refreshToken', refreshToken)
              requests.forEach(cb => cb(token))
              requests = []
              return service(config)
            }).catch(err => {
              isRefreshing = false
              return Promise.reject(err)
            })
        } else {
          return new Promise((resolve) => {
            requests.push(token => {
              config.headers.token = token
              resolve(service(config))
            })
          })
        }
      } else if (code === 1001) {
        reload()
      } else if (code === 5005) {
        // 不做事情
      } else {
        Message.error(msg || 'Error', 5)
      }
      return Promise.reject(data)
    } else {
      return data
    }
  },
  error => {
    let message = error.message
    if (
      error.code && (
        error.code === 'ECONNABORTED' ||
        error.code === 'ETIMEDOUT'
      )
    ) {
      message = '请求超时，请稍后重试'
    } else if (error.message && error.message === 'Network Error') {
      message = '网络未连接或服务正在更新'
    } else if (error.message && error.message === 'Request failed with status code 404') {
      message = '404 请求资源未找到'
    }
    Message.error(message, 5)
    return Promise.reject(error)
  }
)

// 刷新token请求的响应拦截器
refresh.interceptors.response.use(response => {
  const res = response.data
  const { code } = res
  if (code !== 200) {
    reload()
    return Promise.reject(res)
  } else {
    return res
  }
})

export default service
